
package com.initialize.core.filter;

import com.baomidou.mybatisplus.extension.api.IErrorCode;
import com.baomidou.mybatisplus.extension.api.R;
import com.initialize.commom.config.exception.SignException;
import com.initialize.commom.config.exception.TokenException;
import com.initialize.commom.config.system.SiteConfig;
import lombok.Builder;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

/**
 * 全局异常处理
 */
@ControllerAdvice
@RestController
public class GlobalExceptionHandler {

    private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(value = Exception.class)
    public R<ExceptionRequestEntity> defaultErrorHandler(HttpServletRequest req, Exception e) {
        String requestURL = printLogAndGetRequestedUrl(req, e);
        return R.restResult(
                ExceptionRequestEntity.builder()
                        .exception("default_exception")
                        .requestURL(requestURL)
                        .timestamp(System.currentTimeMillis())
                        .build(),
                new IErrorCode() {
                    @Override
                    public long getCode() {
                        return 401;
                    }

                    @Override
                    public String getMsg() {
                        return "请将该信息发送至后端工程师";
                    }
                });
    }

    @ExceptionHandler(value = SignException.class)
    public R<ExceptionRequestEntity> signErrorHandler(HttpServletRequest req, Exception e) {
        String requestURL = printLogAndGetRequestedUrl(req, e);
        return R.restResult(
                ExceptionRequestEntity.builder()
                        .exception("sign_exception")
                        .requestURL(requestURL)
                        .timestamp(System.currentTimeMillis())
                        .build(),
                new IErrorCode() {
                    @Override
                    public long getCode() {
                        return 401;
                    }

                    @Override
                    public String getMsg() {
                        return "请将该信息发送至后端工程师";
                    }
                });
    }

    @ExceptionHandler(value = TokenException.class)
    public R<ExceptionRequestEntity> tokenErrorHandler(HttpServletRequest req, Exception e) {
        String requestURL = printLogAndGetRequestedUrl(req, e);
        return R.restResult(
                ExceptionRequestEntity.builder()
                        .exception("token_exception")
                        .requestURL(requestURL)
                        .timestamp(System.currentTimeMillis())
                        .build(),
                new IErrorCode() {
                    @Override
                    public long getCode() {
                        return 401;
                    }

                    @Override
                    public String getMsg() {
                        return "请将该信息发送至后端工程师";
                    }
                });
    }

    /**
     * 打印日志并且获取异常的请求地址
     *
     * @param req
     * @param e
     * @return
     */
    private String printLogAndGetRequestedUrl(HttpServletRequest req, Exception e) {
        String requestURL = req.getRequestURL().toString();
        String reqRemoteAddr = req.getRemoteAddr();
        String reqRemoteHost = req.getRemoteHost();

        logger.error("ip地址->>  {}", reqRemoteAddr);
        logger.error("主机名->>  {}", reqRemoteHost);
        if (SiteConfig.FLAG) {
            logger.error("Exception->>  ", e);
        } else {
            logger.error("Exception->>  {}", e.getMessage());
        }
        logger.error("RequestURL->>  {}", requestURL);
        return requestURL;
    }

    /**
     * 异常的实体
     */
    @Data
    @Builder
    static
    class ExceptionRequestEntity {
        private long timestamp;
        private String exception;
        private String requestURL;
    }


}